#include "dynamic_json_ui/widget_factory.h"

#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QTextEdit>
#include <QPushButton>
#include <QCheckBox>
#include <QRadioButton>
#include <QSlider>
#include <QSpinBox>
#include <QVBoxLayout>
#include <QHBoxLayout>

#include "dynamic_json_ui/widget_registry.h"
#include "dynamic_json_ui/dynamic_json_ui.h"

namespace dynamic_json_ui {

QWidget *WidgetFactory::createWidget(const JsonUiElement &element,
                                     DynamicJsonUI *owner)
{
    QWidget *widget = nullptr;

    if (element.type == "Label") {
        QLabel *lbl = new QLabel();
        widget = lbl;

        if (element.properties.contains("text")) {
            lbl->setText(element.properties["text"].toString());
        }
    } else if (element.type == "LineEdit") {
        QLineEdit *le = new QLineEdit();
        widget = le;

        if (element.properties.contains("placeholderText")) {
            le->setPlaceholderText(
                element.properties["placeholderText"].toString());
        }

        if (element.properties.contains("text")) {
            le->setText(element.properties["text"].toString());
        }
    } else if (element.type == "ComboBox") {
        QComboBox *cmb = new QComboBox();
        widget = cmb;

        if (element.properties.contains("items")) {
            QStringList items = element.properties["items"].toStringList();
            cmb->addItems(items);
        }

        if (element.properties.contains("currentIndex")) {
            cmb->setCurrentIndex(element.properties["currentIndex"].toInt());
        }
    } else if (element.type == "TextEdit") {
        QTextEdit *te = new QTextEdit();

        if (element.properties.contains("text")) {
            te->setPlainText(element.properties["text"].toString());
        }

        widget = te;
    } else if (element.type == "Button") {
        QPushButton *pbn = new QPushButton();
        widget = pbn;

        if (element.properties.contains("text")) {
            pbn->setText(element.properties["text"].toString());
        }

        if (element._signals.contains("onClicked")) {
            QObject::connect(pbn, &QPushButton::clicked, owner,
                             [owner, func = element._signals["onClicked"]]() {
                                 emit owner->callJsFunction(func);
                             });
        }
    } else if (element.type == "CheckBox") {
        QCheckBox *chk = new QCheckBox();
        widget = chk;

        if (element.properties.contains("text")) {
            chk->setText(element.properties["text"].toString());
        }

        if (element.properties.contains("checked")) {
            chk->setChecked(element.properties["checked"].toBool());
        }
    } else if (element.type == "RadioButton") {
        QRadioButton *rdo = new QRadioButton();
        widget = rdo;

        if (element.properties.contains("text")) {
            rdo->setText(element.properties["text"].toString());
        }

        if (element.properties.contains("checked")) {
            rdo->setChecked(element.properties["checked"].toBool());
        }
    } else if (element.type == "Slider") {
        QSlider *slider = new QSlider(Qt::Horizontal);
        widget = slider;

        if (element.properties.contains("minimum")) {
            slider->setMinimum(element.properties["minimum"].toInt());
        }

        if (element.properties.contains("maximum")) {
            slider->setMaximum(element.properties["maximum"].toInt());
        }

        if (element.properties.contains("value")) {
            slider->setValue(element.properties["value"].toInt());
        }
    } else if (element.type == "SpinBox") {
        QSpinBox *spin = new QSpinBox();
        widget = spin;

        if (element.properties.contains("minimum")) {
            spin->setMinimum(element.properties["minimum"].toInt());
        }

        if (element.properties.contains("maximum")) {
            spin->setMaximum(element.properties["maximum"].toInt());
        }

        if (element.properties.contains("value")) {
            spin->setValue(element.properties["value"].toInt());
        }
    } else if (element.type == "VBoxLayout") {
        QWidget *container = new QWidget();
        widget = container;

        QVBoxLayout *layout = new QVBoxLayout(container);

        for (const auto &child : element.children) {
            layout->addWidget(createWidget(child, owner));
        }

    } else if (element.type == "HBoxLayout") {
        QWidget *container = new QWidget();
        widget = container;

        QHBoxLayout *layout = new QHBoxLayout(container);

        for (const auto &child : element.children) {
            layout->addWidget(createWidget(child, owner));
        }
    }

    if (widget) {
        if (!element.id.isEmpty()) {
            WidgetRegistry::instance().registerWidget(element.id, widget);
        }

        if (!element.style.isEmpty()) {
            widget->setStyleSheet(element.style);
        }
    }

    return widget;
}

} // namespace dynamic_json_ui
